// var gulp = require('gulp');
// var through = require('through2');
// var gutil = require('gulp-util');
// var PluginError = gutil.PluginError;
//
// // var sample = require('gulp-cef');
// gulp.task('cef', function() {
//     gulp.src('source/test.js')
//         .pipe(cef('cocococococo'))
//         .pipe(gulp.dest('dist'));
// });
//
// function prefixStream(prefixText){
//   var stream = through();
//   stream.write(prefixText);
//   return stream;
// }
//
// function cef(prefixText) {
//   if (!prefixText) {
//   //  throw new PluginError(PLUGIN_NAME, 'Missing prefix text!');
//   }
//   prefixText = new Buffer(prefixText);
//   // creating a stream through which each file will pass
//   var stream = through(function(file, encoding,callback) {
//       // do whatever necessary to process the file
//       if (file.isNull()) {
//       }
//       if (file.isBuffer()) {
//         // //文件处理
//         // var data = file.contents.toString();
//         // //data = data + 123;
//         // final = new Buffer(data);
//         // this.push(final);
//       }
//       if (file.isStream()) {
//         var streamer = prefixStream(prefixText);
//
//         // 从 streamer 中捕获错误，并发出一个 gulp的错误
//         streamer.on('error', this.emit.bind(this, 'error'));
//         // 开始转换
//         file.contents = file.contents.pipe(streamer);
//
//       }
//
//       // just pipe data next, or just do nothing to process file later in flushFunction
//       // never forget callback to indicate that the file has been processed.
//       this.push(file);
//       // 告诉 stream 转换工作完成
//       callback();
//     //  callback();
//     });
//   // returning the file stream
//   return stream;
// }


var gulp = require('gulp');
// var gulpPrefixer = require('gulp-prefixer');
gulp.task('cef', function() {
  // gulp.src('source/test.js',{ buffer: false })
   gulp.src('source/test.js')
    .pipe(gulpPrefixer('prepended string\n'))
    .pipe(gulp.dest('dist'));
});



var through = require('through2');
var gutil = require('gulp-util');
var PluginError = gutil.PluginError;

// 常量
const PLUGIN_NAME = 'gulp-prefixer';

function prefixStream(prefixText) {
  var stream = through();
  stream.write(prefixText);
  return stream;
}

// 插件级别函数 (处理文件)
function gulpPrefixer(prefixText) {
  // if (!prefixText) {
  //   throw new PluginError(PLUGIN_NAME, 'Missing prefix text!');
  // }
  //
  // prefixText = new Buffer(prefixText); // 预先分配

  // 创建一个让每个文件通过的 stream 通道
  var stream = through.obj(function(file, enc, cb) {
    if (file.isBuffer()) {
      //文本文件内容
      var buffer = file.contents;
      var str = buffer.toString('utf-8');
      // console.log(str);

      var cefFunction = {}, //总function对象
          functionIndex = 0,
          functionNameArr = []; // 所有函数名称数组
      //找寻function关键字
      var functionIndexLeftArr = [];
      var reg = /function[\s\r\n]*([\w]+)[\s\r\n]*\([\s\S]*?\)[\s\n\r]*\{|,[\s\r\n]*([\w]+)[\s\r\n]*:[\s\r\n]*function[\s\r\n]*\([\s\S]*?\)[\s\n\r]*\{|\{[\s\r\n]*([\w]+)[\s\r\n]*:[\s\r\n]*function[\s\r\n]*\([\s\S]*?\)[\s\n\r]*\{|var[\s\r\n]*([\w]+)[\s\r\n]*=[\s\r\n]*function[\s\r\n]*\([\s\S]*?\)[\s\n\r]*\{|\.([\w]+)[\s\r\n]*=[\s\r\n]*function[\s\r\n]*\([\s\S]*?\)[\s\n\r]*\{/g;  //可能含有空格，可能含有空格和字母数字，可能有空格字母数字和换行
      //测试用例：var str = "Visit W3School,function(a,b){} W3School is a place to study web technology.function as  ( a ,b, v) {}";
      while(reg.exec(str) !== null){
        // console.log('====='+ typeof (RegExp.$1));
        //第一个说明该盘数为普通函数，例如function getName(){}
        if(RegExp.$1 !== ''){
          // console.log(1);
          cefFunction[functionIndex] = [RegExp.$1,reg.lastIndex];

          //第二个参数是,getName:function(){}
        }else if(RegExp.$2 !== ''){
          // console.log(2);
          cefFunction[functionIndex] = [RegExp.$2,reg.lastIndex];

          //第三个参数是{getName:function(){}
        }else if(RegExp.$3 !== ''){
          // console.log(3);
          cefFunction[functionIndex] = [RegExp.$3,reg.lastIndex];
          //第四个参数是var getName = function(){}
        }else if(RegExp.$4 !== ''){
          // console.log(4);
          cefFunction[functionIndex] = [RegExp.$4,reg.lastIndex];

        }else if(RegExp.$5 !== ''){
          // console.log('5');
          cefFunction[functionIndex] = [RegExp.$5,reg.lastIndex];

        }
        //lastIndex-1的目的是为了从0开始计算
        functionIndexLeftArr.push(reg.lastIndex-1);
        functionIndex ++;
        //functionIndexLeftArr.push(reg.lastIndex);
      }
      // console.log('长度：'+functionIndexLeftArr);
      for(var i = 0, len = functionIndexLeftArr.length; i < len; i ++){
        //找到当前的function字符串
        //var nowFunctionStr = str.substring(functionIndexLeftArr[i],functionIndexLeftArr[i+1]);
        functionNameArr.push(cefFunction[i][0]);

        var arrRightSub = cycleStr(str,functionIndexLeftArr,i,1);
        cefFunction[i].push(arrRightSub);
        console.log('循环+++'+arrRightSub);

      }
      console.log(functionNameArr);
      var jsonStr = JSON.stringify(cefFunction);

      file.contents = new Buffer(jsonStr);

    }

    if (file.isStream()) {
      // 定义转换内容的 streamer
      var streamer = prefixStream(prefixText);

      var functionIndexLeftArr = [];
      var reg = /function[\s\S]*\([\s\S]*\)[\s\S]*\{/g;
      while(reg.exec(file.contents.toString())){
        functionIndexLeftArr.push(reg.lastIndex);

      }
      var stream2 = through();
      var jsonStr = JSON.stringify(functionIndexLeftArr);
      stream2.write(file.contents.toString('utf-8'));


      // 从 streamer 中捕获错误，并发出一个 gulp的错误
      streamer.on('error', this.emit.bind(this, 'error'));

      // 开始转换
      file.contents = file.contents.pipe(stream2);
    }

    // 确保文件进去下一个插件
    this.push(file);
    // 告诉 stream 转换工作完成
    cb();
  });

  // 返回文件 stream
  return stream;
}

/**
 * 右花括号匹配算法
 * @param  {String} str                  文件字符串
 * @param  {Array} functionIndexLeftArr 匹配到的function数组
 * @param  {Number} i                    当前数组下标
 * @param  {Number} interval             数组区间跨度
 * @return {Number}                      返回右花括号的位置，从1开始计数
 */
function cycleStr(str,functionIndexLeftArr,i,interval){

  var nowFunctionStr;
  if(interval >= functionIndexLeftArr.length){
    // console.log('1123');
      nowFunctionStr = str.substring(functionIndexLeftArr[i],str.length);
  }else{
      nowFunctionStr = str.substring(functionIndexLeftArr[i],functionIndexLeftArr[i+interval]);
  }

  var hash = {};
  for(var j = 0,len2 = nowFunctionStr.length; j < len2; j ++){
      if(hash[nowFunctionStr.substr(j,1)]){
        hash[nowFunctionStr.substr(j,1)].push(j);
      }else{
        hash[nowFunctionStr.substr(j,1)] = [j];
      }
  }

    var arrLeft = hash['{'] || [];
    var arrRight = hash['}'] || [];
    var arrLeftLength = arrLeft.length;
    var arrRightLength = arrRight.length;
    console.log(arrLeft);
    console.log(arrRight);

    if(arrLeftLength > arrRightLength){

       ++interval;
      return cycleStr(str,functionIndexLeftArr,i,interval);

    }else if(arrLeftLength < arrRightLength){

      for(var y = 0;y < arrRightLength - 1; y ++){
        //第一个右括号的位置如果比第二个做括号的位置小，那么之前得出当前的i即为该函数的右括号
        if(arrRight[1] > arrLeft[0]){
          break;
        }

        //如果左括号的下一个位置大于右括号的前一个位置，那么之前得出当前的i即为该函数的右括号
        if(arrLeft[y+1] > arrRight[y]){
          break;
        }
      }
      return arrRight[y] + functionIndexLeftArr[i] + 1;
    }

    //左右数组只有一个，那么说明刚好全部一一对应
    if(arrLeftLength === 1){
      return arrRight[0] + functionIndexLeftArr[i] + 1;
    }

    for(var x = 0;x < arrLeftLength - 1; x ++){
      //第一个右括号的位置如果比第二个做括号的位置小，那么之前得出当前的i即为该函数的右括号
      if(arrLeft[1] > arrRight[0]){
        break;
      }

      //如果左括号的下一个位置大于右括号的前一个位置，那么之前得出当前的i即为该函数的右括号
      if(arrLeft[x+1] > arrRight[x]){
        break;
      }
    }
    console.log('wo-'+arrRight[x]);
    return arrRight[x] + functionIndexLeftArr[i] + 1;
}
